package au.com.finalconcept.roo.addon.behaviours;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.lang3.Validate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.springframework.roo.classpath.TypeLocationService;
import org.springframework.roo.classpath.TypeManagementService;
import org.springframework.roo.classpath.details.MemberFindingUtils;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetailsBuilder;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadata;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.project.ProjectOperations;
import org.springframework.roo.project.Dependency;
import org.springframework.roo.project.DependencyScope;
import org.springframework.roo.project.DependencyType;
import org.springframework.roo.project.Repository;
import org.springframework.roo.support.util.XmlUtils;
import org.w3c.dom.Element;

/**
 * Implementation of operations this add-on offers.
 * 
 * @since 1.1
 */
@Component
// Use these Apache Felix annotations to register your commands class in the Roo
// container
@Service
public class BehavioursOperationsImpl implements BehavioursOperations {

    /**
     * Use ProjectOperations to install new dependencies, plugins, properties,
     * etc into the project configuration
     */
    @Reference
    private ProjectOperations projectOperations;

    /**
     * Use TypeLocationService to find types which are annotated with a given
     * annotation in the project
     */
    @Reference
    private TypeLocationService typeLocationService;

    /**
     * Use TypeManagementService to change types
     */
    @Reference
    private TypeManagementService typeManagementService;

    /** {@inheritDoc} */
    public void setup() {
        // Install the add-on Google code repository needed to get the
        // annotation
        projectOperations.addRepository("", new Repository(
                "Behaviours Roo add-on repository",
                    "Behaviours Roo add-on repository",
                    "https://spring-roo-behaviours.googlecode.com/svn/repo"));
    
        List<Dependency> dependencies = new ArrayList<Dependency>();
    
        // Install the dependency on the add-on jar (
        dependencies.add(new Dependency(
                "au.com.finalconcept.roo.addon.behaviours",
                    "spring-roo-behaviours",
                    "0.1.1.BUILD-SNAPSHOT",
                    DependencyType.JAR,
                    DependencyScope.PROVIDED));
    
        // Install dependencies defined in external XML file
        for (Element dependencyElement : XmlUtils.findElements(
                "/configuration/batch/dependencies/dependency",
                    XmlUtils.getConfiguration(getClass()))) {
            dependencies.add(new Dependency(dependencyElement));
        }
    
        // Add all new dependencies to pom.xml
        projectOperations.addDependencies("", dependencies);
    }

    /** {@inheritDoc} */
    public boolean isCommandAvailable() {
        // Check if a project has been created
        return projectOperations.isFocusedProjectAvailable();
    }

    public void annotateSoftDeleteAll() {
        // Use the TypeLocationService to scan project for all types with a
        // specific annotation
        for (JavaType type : typeLocationService
                .findTypesWithAnnotation(new JavaType("org.springframework.roo.addon.javabean.RooJavaBean"))) {
            annotateSoftDeleteType(type);
        }

    }

    /** {@inheritDoc} */
    public void annotateSoftDeleteType(JavaType javaType) {
        Util.annotateIfNeeded(typeLocationService, typeManagementService, javaType, new JavaType(RooSoftDelete.class), null);
    }

    public void annotateTimestampableAll() {
        // Use the TypeLocationService to scan project for all types with a
        // specific annotation
        for (JavaType type : typeLocationService
                .findTypesWithAnnotation(new JavaType("org.springframework.roo.addon.javabean.RooJavaBean"))) {
            annotateTimestampableType(type);
        }

    }

    public void annotateTimestampableType(JavaType javaType) {

        Util.annotateIfNeeded(this.typeLocationService, this.typeManagementService, javaType, new JavaType(RooTimestampable.class), null);

    }
    
    public void annotateSlugableType(JavaType javaType, String fields) {

        HashMap<String, String> attributes;
        
        attributes = new HashMap<String, String>();
        attributes.put("fields", fields);
        
        Util.annotateIfNeeded(this.typeLocationService, this.typeManagementService, javaType, new JavaType(RooSlugable.class), attributes);

    }

}